package response

import (
	"errors"
	"github.com/adwindone/sdk-go/model/common"
	"github.com/adwindone/sdk-go/util/hexutil"
	"strconv"
	"strings"
)

type NodeStatus struct {
	IsSync          bool           `json:"is_sync"`
	IsDanger        bool           `json:"is_danger"`
	InitBlockNumber uint64         `json:"init_block_number"`
	PeersCount      uint64         `json:"peers_count"`
	Version         string         `json:"version"`
	SelfStatus      *PeersStatus   `json:"self_status"`
	PeersStatus     []*PeersStatus `json:"peers_status"`
}

type PeersStatus struct {
	Height  uint64        `json:"height"`
	Address hexutil.Bytes `json:"address"`
	NetInfo *NetInfo      `json:"net_info,omitempty"`
}

type NetInfo struct {
	Domain string `json:"domain"`
	Host   string `json:"host"`
	Origin string `json:"origin"`
	Port   int    `json:"port"`
}

// NodeStatus结构转换
func NodeStatusConvert(data *common.NodeStatus) (*NodeStatus, error) {
	info := new(NodeStatus)
	info.IsSync = data.IsSync
	info.IsDanger = data.IsDanger
	info.InitBlockNumber = data.InitBlockNumber
	info.PeersCount = data.PeersCount
	info.Version = data.Version
	// self status
	selfStatus := new(PeersStatus)
	selfStatus.Address = data.SelfStatus.Address
	selfStatus.Height = data.SelfStatus.Height
	info.SelfStatus = selfStatus
	// peers status
	peersStatus := make([]*PeersStatus, 0)
	for _, v := range data.PeersStatus {
		ps := new(PeersStatus)
		ps.Address = v.Address
		ps.Height = v.Height
		// node net info
		netInfo := new(NetInfo)
		netInfo.Origin = hexutil.EncodeUint64(v.NodeNetInfo.Origin)
		domain, host, port, err := multiAddressParse(v.NodeNetInfo.MultiAddress)
		if err != nil {
			return nil, err
		}
		netInfo.Domain = domain
		netInfo.Host = host
		netInfo.Port = port
		ps.NetInfo = netInfo
		peersStatus = append(peersStatus, ps)
	}
	info.PeersStatus = peersStatus
	return info, nil
}

func multiAddressParse(s string) (string, string, int, error) {
	data := strings.Split(s, "/")
	if len(data) < 6 {
		return "", "", 0, errors.New("multiAddress data format error")
	}
	port, err := strconv.ParseInt(data[4], 10, 32)
	if err != nil {
		return "", "", 0, err
	}
	return data[6], data[2], int(port), nil
}
